package com.example.forum.controller;

import com.example.forum.common.AppResult;
import com.example.forum.common.ResultCode;
import com.example.forum.config.AppConfig;
import com.example.forum.model.Message;
import com.example.forum.model.User;
import com.example.forum.services.IMessageService;
import com.example.forum.services.IUserService;
import javax.validation.constraints.NotNull;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.List;

@RestController
@RequestMapping("/message")
@Api(tags = "站内信接口")
@Slf4j
public class MessageController {

    @Resource
    private IMessageService messageService;

    @Resource
    private IUserService userService;

    @ApiOperation("/发送站内信")
    @PostMapping("/send")
    public AppResult send(HttpServletRequest request,
                          @ApiParam("接收者id") @RequestParam("receiveUserId") @NotNull Long receiveUserId,
                          @ApiParam("发送正文") @RequestParam("content") @NotNull String content,
                          @ApiParam("消息类型") @RequestParam(value = "type", required = false, defaultValue = "private") String type){
        //获取当前用户信息
        HttpSession session=request.getSession(false);
        
        // 记录授权头信息
        String authHeader = request.getHeader("Authorization");
        
        User user = null;
        
        // 首先尝试从Authorization头获取用户（优先级更高，可以覆盖session中的用户）
        if (authHeader != null && !authHeader.isEmpty()) {
            log.info("开始从Authorization头解析用户信息: {}", authHeader);
            
            try {
                // 处理格式为 "用户已登录-username-timestamp" 的token
                if (authHeader.contains("-")) {
                    String[] parts = authHeader.split("-");
                    if (parts.length > 1) {
                        String username = parts[1]; // 第二部分应该是用户名
                        log.info("从Authorization头提取的用户名: {}", username);
                        
                        // 通过用户名查找用户
                        user = userService.selectByUsername(username);
                        if (user != null) {
                            log.info("根据Authorization头找到用户: id={}, username={}", user.getId(), user.getUsername());
                            
                            // 更新会话中的用户信息
                            if (session != null) {
                                session.setAttribute(AppConfig.USER_SESSION, user);
                                log.info("已将从Authorization获取到的用户信息更新到会话中");
                            } else {
                                log.warn("会话不存在，无法更新用户信息");
                            }
                        } else {
                            log.warn("从Authorization获取用户失败: 未找到用户名为{}的用户", username);
                        }
                    }
                }
            } catch (Exception e) {
                log.error("解析Authorization头出错", e);
            }
        }
        
        // 如果从Authorization头没有获取到用户，尝试从会话获取用户
        if (user == null && session != null) {
            user = (User) session.getAttribute(AppConfig.USER_SESSION);
            if (user != null) {
                log.info("从会话获取到用户: id={}, username={}", user.getId(), user.getUsername());
            }
        }
        
        // 如果用户仍然为null，返回错误
        if (user == null) {
            log.warn("发送站内信失败: 用户未登录");
            return AppResult.failed(ResultCode.FAILED_USER_NOT_EXISTS);
        }
        
        // 记录当前用户信息
        log.info("当前登录用户信息: id={}, username={}", user.getId(), user.getUsername());
        
        // 增加详细日志，记录接收者ID和用户ID的比较结果
        log.info("检查是否自己给自己发消息: 当前用户ID={}, 接收者ID={}, 是否相等={}", 
                user.getId(), receiveUserId, receiveUserId.equals(user.getId()));
        
        //禁言状态 不能发送站内信
        if(user.getState()==1) {
            log.warn(ResultCode.FAILED_USER_BANNED.toString());
            return AppResult.failed(ResultCode.FAILED_USER_BANNED);
        }
        //不能自己给自己发送
        if(receiveUserId.equals(user.getId())){
            log.warn("不能自己给自己发站内信 postUserid= "+user.getId()+" receiveUserId ="+receiveUserId);
            return AppResult.failed("不能自己给自己发站内信!");
        }
        //判断接收者是否存在
        User receiveUser = userService.selectById(receiveUserId);
        if(receiveUser==null||receiveUser.getId()<=0||receiveUser.getDeleteState()!=0){
            //打印日志
            log.warn("接收者不存在或状态异常: receiveUserId={}, 接收者状态={}", 
                    receiveUserId, 
                    receiveUser != null ? "删除状态:" + receiveUser.getDeleteState() : "不存在");
            return AppResult.failed("接收者状态异常");
        }
        
        // 验证消息类型
        if (!isValidMessageType(type)) {
            log.warn("无效的消息类型: {}", type);
            return AppResult.failed("无效的消息类型");
        }
        
        //构造数据
        Message message=new Message();
        message.setContent(content);
        message.setPostUserId(user.getId());
        message.setReceiveUserId(receiveUserId);
        message.setType(type); // 设置消息类型
        messageService.create(message);
        
        log.info("发送站内信成功: 发送者={}, 接收者={}, 类型={}", user.getId(), receiveUserId, type);
        return AppResult.success("发送成功");
    }
    
    /**
     * 验证消息类型是否有效
     * @param type 消息类型
     * @return 是否有效
     */
    private boolean isValidMessageType(String type) {
        return type != null && (
            type.equals("system") || 
            type.equals("comment") || 
            type.equals("like") || 
            type.equals("notice") ||
            type.equals("private")
        );
    }

    @ApiOperation("获取当前用户未读站内信数量")
    @GetMapping("/getUnreadCount")
    public AppResult<Integer> getUnreadCount(HttpServletRequest request){
        HttpSession session=request.getSession(false);
        User user= (User) session.getAttribute(AppConfig.USER_SESSION);
        if (user == null) {
            log.warn("获取未读站内信数量失败：用户未登录");
            return AppResult.failed(ResultCode.FAILED_USER_NOT_EXISTS);
        }
        //调用dao
        int result = messageService.selectUnreadCount(user.getId());
        return AppResult.success(result);
    }

    @ApiOperation("获取当前用户所有站内信")
    @GetMapping("/getAll")
    public AppResult<List<Message>> getAll(
            HttpServletRequest request,
            @ApiParam("消息类型") @RequestParam(value = "type", required = false) String type,
            @ApiParam("消息状态：0-未读，1-已读，2-已回复") @RequestParam(value = "status", required = false) Byte status,
            @ApiParam("页码") @RequestParam(value = "page", required = false, defaultValue = "1") Integer page,
            @ApiParam("每页条数") @RequestParam(value = "size", required = false, defaultValue = "10") Integer size
    ) {
        HttpSession session = request.getSession(false);
        User user = (User) session.getAttribute(AppConfig.USER_SESSION);
        
        if (user == null) {
            log.warn("获取站内信失败：用户未登录");
            return AppResult.failed(ResultCode.FAILED_USER_NOT_EXISTS);
        }
        
        log.info("开始获取用户ID={}的站内信, 类型={}, 状态={}, 页码={}, 每页条数={}", 
                user.getId(), type, status, page, size);
        
        try {
            // 获取包含发送者信息的消息列表
            List<Message> messages = messageService.selectByReceiveUserIdWithUserInfo(user.getId());
            
            // 手动处理分页和筛选
            List<Message> filteredMessages = messages.stream()
                .filter(msg -> {
                    // 类型过滤
                    if (type != null && !type.isEmpty() && !type.equals(msg.getType())) {
                        return false;
                    }
                    // 状态过滤
                    if (status != null && !status.equals(msg.getState())) {
                        return false;
                    }
                    return true;
                })
                .skip((long) (page - 1) * size)
                .limit(size)
                .collect(java.util.stream.Collectors.toList());
            
            log.info("获取站内信成功：用户ID={}, 消息数量={}", user.getId(), filteredMessages.size());
            if (filteredMessages.isEmpty()) {
                log.warn("用户ID={}没有符合条件的站内信或查询结果为空", user.getId());
            }
            
            return AppResult.success(filteredMessages);
        } catch (Exception e) {
            log.error("获取站内信异常：用户ID={}, 错误={}", user.getId(), e.getMessage(), e);
            return AppResult.failed("获取站内信失败：" + e.getMessage());
        }
    }

    @ApiOperation("更改指定站内信为已读")
    @PostMapping("/markRead")
    public AppResult markRead(@ApiParam("站内信id") @RequestParam("id") @NotNull Long id,HttpServletRequest request){

        //根据id查询内容
        HttpSession session=request.getSession(false);
        User user= (User) session.getAttribute(AppConfig.USER_SESSION);
        //查询站内信表
        Message message=messageService.selectById(id);
        //判断当前文章是否存在
        if(message==null||message.getDeleteState()==1){
            return AppResult.failed(ResultCode.FAILED_Message_NOT_EXISTS);
        }
        //校验站内信是不是自己的
        if(!message.getReceiveUserId().equals(user.getId())){
            return AppResult.failed(ResultCode.FAILED_FORBIDDEN);
        }

        //更新状态为已读
        messageService.updateStateById(id, (byte) 1);

        return AppResult.success();
    }

    @ApiOperation("标记当前用户所有站内信为已读")
    @PostMapping("/markAllRead")
    public AppResult markAllRead(HttpServletRequest request) {
        HttpSession session = request.getSession(false);
        User user = (User) session.getAttribute(AppConfig.USER_SESSION);
        
        if (user == null) {
            log.warn("标记全部已读失败：用户未登录");
            return AppResult.failed(ResultCode.FAILED_USER_NOT_EXISTS);
        }
        
        try {
            // 调用Service层方法，将当前用户的所有未读消息标记为已读
            messageService.markAllAsRead(user.getId());
            log.info("用户ID={}的所有消息已标记为已读", user.getId());
            return AppResult.success("所有消息已标记为已读");
        } catch (Exception e) {
            log.error("标记全部已读异常：用户ID={}, 错误={}", user.getId(), e.getMessage(), e);
            return AppResult.failed("标记全部已读失败：" + e.getMessage());
        }
    }

    @ApiOperation("删除指定站内信")
    @PostMapping("/delete")
    public AppResult delete(@ApiParam("站内信id") @RequestParam("id") @NotNull Long id, HttpServletRequest request) {
        HttpSession session = request.getSession(false);
        User user = (User) session.getAttribute(AppConfig.USER_SESSION);
        
        if (user == null) {
            log.warn("删除站内信失败：用户未登录");
            return AppResult.failed(ResultCode.FAILED_USER_NOT_EXISTS);
        }
        
        try {
            // 查询站内信表
            Message message = messageService.selectById(id);
            
            // 判断消息是否存在
            if (message == null || message.getDeleteState() == 1) {
                log.warn("删除站内信失败：消息不存在, ID={}", id);
                return AppResult.failed(ResultCode.FAILED_Message_NOT_EXISTS);
            }
            
            // 校验站内信是不是自己的
            if (!message.getReceiveUserId().equals(user.getId())) {
                log.warn("删除站内信失败：无权限, 消息ID={}, 用户ID={}", id, user.getId());
                return AppResult.failed(ResultCode.FAILED_FORBIDDEN);
            }
            
            // 逻辑删除消息
            messageService.deleteMessage(id);
            log.info("站内信删除成功：消息ID={}, 用户ID={}", id, user.getId());
            
            return AppResult.success("删除成功");
        } catch (Exception e) {
            log.error("删除站内信异常：消息ID={}, 用户ID={}, 错误={}", id, user.getId(), e.getMessage(), e);
            return AppResult.failed("删除站内信失败：" + e.getMessage());
        }
    }


    @ApiOperation("回复站内信")
    @PostMapping("/reply")
    public AppResult reply(@ApiParam("回复站内信id") @RequestParam("repliedId") @NotNull Long repliedId,
                           @ApiParam("回复正文") @RequestParam("content") @NotNull String content,
                           @ApiParam("消息类型") @RequestParam(value = "type", required = false) String type,
                           HttpServletRequest request){
        //获取当前登录用户
        HttpSession session=request.getSession(false);
        User user= (User) session.getAttribute(AppConfig.USER_SESSION);
        //校验用户状态
        if(user.getState()==1){
            return AppResult.failed(ResultCode.FAILED_USER_BANNED);
        }
        //根据站内信id 查询要回复的站内信
        Message existsMessage=messageService.selectById(repliedId);
        //校验要回复的站内信的状态
        if(existsMessage==null||existsMessage.getDeleteState()==1){
            return AppResult.failed(ResultCode.FAILED_Message_NOT_EXISTS);
        }
        //不能自己给自己回复站内信
        if(user.getId().equals(existsMessage.getPostUserId())){
            return AppResult.failed("不能自己给自己回复站内信");
        }
        
        // 如果没有指定type，则继承原消息的类型
        String messageType = type;
        if (messageType == null || messageType.isEmpty()) {
            messageType = existsMessage.getType();
            // 如果原消息也没有类型，则默认为private（私信）
            if (messageType == null || messageType.isEmpty()) {
                messageType = "private";
            }
        } else if (!isValidMessageType(messageType)) {
            // 如果指定了type但不是有效类型，则返回错误
            log.warn("无效的消息类型: {}", messageType);
            return AppResult.failed("无效的消息类型");
        }
        
        //构造站内信
        Message message=new Message();
        message.setPostUserId(user.getId());
        message.setReceiveUserId(existsMessage.getPostUserId());
        message.setContent(content);
        message.setType(messageType); // 设置消息类型
        
        //调用Services
        messageService.reply(repliedId, message);
        
        log.info("回复站内信成功: 回复者={}, 接收者={}, 原消息ID={}, 类型={}", 
                user.getId(), existsMessage.getPostUserId(), repliedId, messageType);
        return AppResult.success();
    }

    @ApiOperation("获取消息分类数量")
    @GetMapping("/category-counts")
    public AppResult<java.util.Map<String, Integer>> getCategoryCounts(HttpServletRequest request) {
        HttpSession session = request.getSession(false);
        User user = (User) session.getAttribute(AppConfig.USER_SESSION);
        
        if (user == null) {
            log.warn("获取消息分类计数失败：用户未登录");
            return AppResult.failed(ResultCode.FAILED_USER_NOT_EXISTS);
        }
        
        try {
            // 调用服务获取分类计数
            java.util.Map<String, Integer> counts = messageService.getCategoryCounts(user.getId());
            log.info("获取消息分类计数成功：用户ID={}, 分类计数={}", user.getId(), counts);
            return AppResult.success(counts);
        } catch (Exception e) {
            log.error("获取消息分类计数异常：用户ID={}, 错误={}", user.getId(), e.getMessage(), e);
            return AppResult.failed("获取消息分类计数失败：" + e.getMessage());
        }
    }

    @ApiOperation("按类型标记消息为已读")
    @PostMapping("/markReadByType")
    public AppResult markReadByType(
            @ApiParam("消息类型") @RequestParam(value = "type", required = false) String type,
            HttpServletRequest request) {
        HttpSession session = request.getSession(false);
        User user = (User) session.getAttribute(AppConfig.USER_SESSION);
        
        if (user == null) {
            log.warn("按类型标记消息已读失败：用户未登录");
            return AppResult.failed(ResultCode.FAILED_USER_NOT_EXISTS);
        }
        
        try {
            // 调用服务按类型标记为已读
            int updatedCount = messageService.markReadByType(user.getId(), type);
            log.info("按类型标记消息已读成功：用户ID={}, 类型={}, 更新数量={}", user.getId(), type, updatedCount);
            
            return AppResult.success("已标记为已读");
        } catch (Exception e) {
            log.error("按类型标记消息已读异常：用户ID={}, 类型={}, 错误={}", user.getId(), type, e.getMessage(), e);
            return AppResult.failed("标记已读失败：" + e.getMessage());
        }
    }
}
